package com.ruoyi.factorydata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.CacheSupportUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.uuid.Seq;
import com.ruoyi.factorydata.domain.CustomerData;
import com.ruoyi.factorydata.domain.ProductionProject;
import com.ruoyi.factorydata.domain.ProductionProjectProductionInfo;
import com.ruoyi.factorydata.domain.ProjectProductionPlan;
import com.ruoyi.factorydata.domain.dto.ProductionProjectDTO;
import com.ruoyi.factorydata.domain.vo.ProductionProjectVo;
import com.ruoyi.factorydata.mapper.*;
import com.ruoyi.factorydata.service.IProductionProjectService;
import com.ruoyi.factorydata.service.IProjectProductionPlanService;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 生产项目Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-24
 */
@Service
public class ProductionProjectServiceImpl extends ServiceImpl<ProductionProjectMapper, ProductionProject> implements IProductionProjectService {
    @Autowired
    private ProductionProjectMapper productionProjectMapper;

    @Autowired
    private ProductionProjectProductionInfoMapper productionProjectProductionInfoMapper;

    @Autowired
    @Lazy
    private IProjectProductionPlanService projectProductionPlanService;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private CustomerDataMapper customerDataMapper;

    @Autowired
    private WorkOrderInfoMapper workOrderInfoMapper;
    @Autowired
    private MaterialRequisitionCodeDetialMapper materialRequisitionCodeDetialMapper;

    /**
     * 查询生产项目
     *
     * @param id 生产项目主键
     * @return 生产项目
     */
    @Override
    public ProductionProjectVo selectProductionProjectById(Long id) {
        ProductionProject project = productionProjectMapper.selectProductionProjectById(id);
        List<ProductionProjectProductionInfo> productionProjectProductionInfos = productionProjectProductionInfoMapper.selectList(new QueryWrapper<ProductionProjectProductionInfo>().lambda()
                .eq(ProductionProjectProductionInfo::getProjectId, id));
        CustomerData customerData = customerDataMapper.selectCustomerDataById(project.getCustomerId());
        SysUser sysUser = userMapper.selectUserById(Long.parseLong(project.getCreateBy()));
        SysUser manger = userMapper.selectUserById(project.getProjectManager());
        return ProductionProjectVo.builder()
                .id(project.getId())
                .projectCode(project.getProjectCode())
                .productionOrderNumber(project.getProductionOrderNumber())
                .customerId(project.getCustomerId())
                .customerName(Optional.ofNullable(customerData).map(CustomerData::getCustomerName).orElse(""))
                .customerCode(Optional.ofNullable(customerData).map(CustomerData::getCustomerCode).orElse(""))
                .orderSource(project.getOrderSource())
                .templateId(project.getTemplateId())
                .priority(project.getPriority())
                .characterizationRequirement(project.getCharacterizationRequirement())
                .surfaceRequirement(project.getSurfaceRequirement())
                .projectManager(project.getProjectManager())
                .projectManagerName(Optional.ofNullable(manger).map(SysUser::getUserName).orElse(""))
                .status(project.getStatus())
                .target(project.getTarget())
                .attachments(project.getAttachments())
                .remark(project.getRemark())
                .delFlag(project.getDelFlag())
                .version(project.getVersion())
                .createBy(project.getCreateBy())
                .createByName(Optional.ofNullable(sysUser).map(SysUser::getUserName).orElse(""))
                .createTime(project.getCreateTime())
                .updateTime(project.getUpdateTime())
                .productionProjectProductionInfoList(productionProjectProductionInfos)
                .build();
    }

    /**
     * 查询生产项目列表
     *
     * @param productionProject 生产项目
     * @return 生产项目
     */
    @Override
    public List<ProductionProjectVo> selectProductionProjectList(ProductionProject productionProject) {
        List<ProductionProject> productionProjects = productionProjectMapper.selectProductionProjectList(productionProject);
        List<ProductionProjectVo> productionLineDataVoList = productionProjects.stream().map(project -> {

            List<ProductionProjectProductionInfo> productionProjectProductionInfoList = productionProjectProductionInfoMapper.selectList(new QueryWrapper<ProductionProjectProductionInfo>().lambda().eq(ProductionProjectProductionInfo::getProjectId, project.getId()));
            return ProductionProjectVo.builder()
                    .id(project.getId())
                    .productionOrderNumber(project.getProductionOrderNumber())
                    .customerId(project.getCustomerId())
                    .orderSource(project.getOrderSource())
                    .templateId(project.getTemplateId())
                    .priority(project.getPriority())
                    .characterizationRequirement(project.getCharacterizationRequirement())
                    .surfaceRequirement(project.getSurfaceRequirement())
                    .projectManager(project.getProjectManager())
                    .productionProjectProductionInfoList(productionProjectProductionInfoList)
                    .delFlag(project.getDelFlag())
                    .version(project.getVersion())
                    .createBy(project.getCreateBy())
                    .createTime(project.getCreateTime())
                    .build();
        }).collect(Collectors.toList());
        Page<ProductionProject> queryData=(Page<ProductionProject>)productionProjects;
        Page<ProductionProjectVo> page = new Page<>(queryData.getPageNum(), queryData.getPageSize());
        page.setTotal(queryData.getTotal());
        page.addAll(productionLineDataVoList);
        return page;
    }

    @Override
    public List<SysUser> selectUserList(SysUser user) {
        return userMapper.selectUserList(user);
    }

    /**
     * 新增生产项目
     *
     * @param productionProjectDTO 生产项目
     * @return 结果
     */
    @Transactional
    @Override
    public int insertProductionProject(ProductionProjectDTO productionProjectDTO) {
        ProductionProject productionProject = new ProductionProject();
        // 生成项目编号
        productionProject.setProjectCode("PR_" + Seq.getId());
        productionProject.setProductionOrderNumber(productionProjectDTO.getProductionOrderNumber());
        productionProject.setCustomerId(productionProjectDTO.getCustomerId());
        productionProject.setOrderSource(productionProjectDTO.getOrderSource());
        productionProject.setTemplateId(productionProjectDTO.getTemplateId());
        productionProject.setPriority(productionProjectDTO.getPriority());
        productionProject.setCharacterizationRequirement(productionProjectDTO.getCharacterizationRequirement());
        productionProject.setSurfaceRequirement(productionProjectDTO.getSurfaceRequirement());
        productionProject.setProjectManager(productionProjectDTO.getProjectManager());
        productionProject.setTarget(productionProjectDTO.getTarget());
        productionProject.setAttachments(productionProjectDTO.getAttachments());
        productionProject.setRemark(productionProjectDTO.getRemark());
        productionProject.setStatus("0");
        productionProject.setCreateBy(productionProjectDTO.getCreateBy());
        productionProject.setCreateTime(DateUtils.getNowDate());
        int i = productionProjectMapper.insertProductionProject(productionProject);
        if (i > 0) {
            productionProjectDTO.getProductionProjectProductionInfoList().forEach(item -> {
                ProductionProjectProductionInfo productionProjectProductionInfo = new ProductionProjectProductionInfo();
                productionProjectProductionInfo.setProjectId(productionProject.getId());
                productionProjectProductionInfo.setProductionBomId(item.getProductionBomId());
                productionProjectProductionInfo.setMaterialId(item.getMaterialId());
                productionProjectProductionInfo.setMaterialCode(item.getMaterialCode());
                productionProjectProductionInfo.setMaterialName(item.getMaterialName());
                productionProjectProductionInfo.setMaterialSpecification(item.getMaterialSpecification());
                productionProjectProductionInfo.setMaterialUnit(item.getMaterialUnit());
                productionProjectProductionInfo.setMaterialUnitName(item.getMaterialUnitName());
                productionProjectProductionInfo.setPlannedProduction(item.getPlannedProduction());
                productionProjectProductionInfo.setDeliveryDate(item.getDeliveryDate());
                productionProjectProductionInfo.setRemark(item.getRemark());
                productionProjectProductionInfo.setStatus("0");
                productionProjectProductionInfo.setCreateBy(productionProjectDTO.getCreateBy());
                productionProjectProductionInfoMapper.insertProductionProjectProductionInfo(productionProjectProductionInfo);
            });
        }
        return i;
    }

    /**
     * 修改生产项目
     *
     * @param productionProjectDTO 生产项目
     * @return 结果
     */
    @Transactional
    @Override
    public int updateProductionProject(ProductionProjectDTO productionProjectDTO) {
        ProductionProject productionProject = new ProductionProject();
        productionProject.setId(productionProjectDTO.getId());
        productionProject.setProductionOrderNumber(productionProjectDTO.getProductionOrderNumber());
        productionProject.setCustomerId(productionProjectDTO.getCustomerId());
        productionProject.setOrderSource(productionProjectDTO.getOrderSource());
        productionProject.setTemplateId(productionProjectDTO.getTemplateId());
        productionProject.setPriority(productionProjectDTO.getPriority());
        productionProject.setCharacterizationRequirement(productionProjectDTO.getCharacterizationRequirement());
        productionProject.setSurfaceRequirement(productionProjectDTO.getSurfaceRequirement());
        productionProject.setTarget(productionProjectDTO.getTarget());
        productionProject.setAttachments(productionProjectDTO.getAttachments());
        productionProject.setProjectManager(productionProjectDTO.getProjectManager());
        productionProject.setRemark(productionProjectDTO.getRemark());
        productionProject.setUpdateTime(DateUtils.getNowDate());
        int i = productionProjectMapper.updateProductionProject(productionProject);
        if (i > 0) {
            int delete = productionProjectProductionInfoMapper.delete(new QueryWrapper<ProductionProjectProductionInfo>().lambda()
                    .eq(ProductionProjectProductionInfo::getProjectId, productionProject.getId()));
            if (productionProjectDTO.getProductionProjectProductionInfoList() != null && !productionProjectDTO.getProductionProjectProductionInfoList().isEmpty()) {
                productionProjectDTO.getProductionProjectProductionInfoList().forEach(productionProjectProductionInfo -> {
                    productionProjectProductionInfo.setId(null);
                    productionProjectProductionInfo.setProjectId(productionProject.getId());
                    productionProjectProductionInfo.setProductionBomId(productionProjectProductionInfo.getProductionBomId());
                    productionProjectProductionInfo.setMaterialId(productionProjectProductionInfo.getMaterialId());
                    productionProjectProductionInfo.setMaterialCode(productionProjectProductionInfo.getMaterialCode());
                    productionProjectProductionInfo.setMaterialName(productionProjectProductionInfo.getMaterialName());
                    productionProjectProductionInfo.setMaterialSpecification(productionProjectProductionInfo.getMaterialSpecification());
                    productionProjectProductionInfo.setMaterialUnit(productionProjectProductionInfo.getMaterialUnit());
                    productionProjectProductionInfo.setMaterialUnitName(productionProjectProductionInfo.getMaterialUnitName());
                    productionProjectProductionInfo.setPlannedProduction(productionProjectProductionInfo.getPlannedProduction());
                    productionProjectProductionInfo.setDeliveryDate(productionProjectProductionInfo.getDeliveryDate());
                    productionProjectProductionInfo.setStatus(productionProjectProductionInfo.getStatus() != null && !productionProjectProductionInfo.getStatus().isBlank() ? productionProjectProductionInfo.getStatus() : "0");
                    productionProjectProductionInfo.setRemark(productionProjectProductionInfo.getRemark());
                    productionProjectProductionInfo.setCreateTime(DateUtils.getNowDate());
                    productionProjectProductionInfo.setCreateBy(productionProjectDTO.getCreateBy());
                    productionProjectProductionInfoMapper.insertProductionProjectProductionInfo(productionProjectProductionInfo);
                });
                // 删除与之关联的计划
                projectProductionPlanService.remove(new QueryWrapper<ProjectProductionPlan>().lambda()
                        .eq(ProjectProductionPlan::getProjectId, productionProjectDTO.getId()));
            }
        }
        return i;
    }

    /**
     * 批量删除生产项目
     *
     * @param ids 需要删除的生产项目主键
     * @return 结果
     */
    @Override
    public int deleteProductionProjectByIds(Long[] ids) {
        return productionProjectMapper.deleteProductionProjectByIds(ids);
    }

    /**
     * 删除生产项目信息
     *
     * @param id 生产项目主键
     * @return 结果
     */
    @Override
    public int deleteProductionProjectById(Long id) {
        return productionProjectMapper.deleteProductionProjectById(id);
    }

    @Override
    public ProductionProject selectProductionProjectByIdAndCache(Long id, Map<Long, ProductionProject> cache) {
        return CacheSupportUtils.getFromCacheOrDB(id, cache, this::getById, productionProject -> productionProject, false);
    }

    @Override
    @Transactional
    public int cancel(Long projectId) {
        Assert.notNull(projectId, "项目id不能为空");
        ProductionProject productionProject = getById(projectId);
        Assert.notNull(productionProject, "项目不存在");
        Assert.isTrue(Integer.parseInt(productionProject.getStatus()) < 3, "项目无法作废");
        productionProject.setStatus("4");
        productionProject.setUpdateTime(DateUtils.getNowDate());
        int update = productionProjectMapper.updateProductionProject(productionProject);
        if (update > 0) {
            //更新项目下所有计划状态为已作废
            update = projectProductionPlanService.cancelByProject(projectId);
            Assert.isTrue(update > 0, "更新项目下所有计划状态为已作废失败");
        }
        return update;
    }

    @Override
    public int finish(Long projectId) {
        Assert.notNull(projectId, "项目id不能为空");
        ProductionProject productionProject = getById(projectId);
        Assert.notNull(productionProject, "项目不存在");
        Assert.isTrue(Integer.parseInt(productionProject.getStatus()) ==2, "项目未开始无法关闭");
        //是否存在未完成工单
        Integer num=workOrderInfoMapper.getRunWorkOrder(projectId);
        num=num==null?0:num;
        Assert.isTrue(num==0, "项目存在未完成工单，无法关闭");
        //是否存在母版未退还情况
        Integer modelNum=materialRequisitionCodeDetialMapper.getNotReturnModelNum(projectId);
        modelNum=modelNum==null?0:modelNum;
        Assert.isTrue(modelNum==0, "项目存在未退还的母版，无法关闭");
        productionProject.setStatus("3");
        productionProject.setUpdateTime(DateUtils.getNowDate());
        return productionProjectMapper.updateProductionProject(productionProject);
    }
}